home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / bit / src / marking.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  44KB  |  1,733 lines

  1. /*
  2.  * $Id: marking.c,v 0.91 1994/02/20 00:53:16 zhao Pre-Release $
  3.  *
  4.  *. This file is part of BIT shareware package. After the two weeks of
  5.  *  free evaluation period, you are encouraged (required) to register
  6.  *  your copy for a small registration fee, which is $35 for personal use
  7.  *  and $50 for commercial, government and institutional use.
  8.  *
  9.  *  Copyright(c) 1993, 1994 by T.C. Zhao.
  10.  *  All rights reserved.
  11.  *
  12.  *  Permission to use, copy, and distribute this software in its entirety
  13.  *  for non-commercial purposes is hereby granted, provided that the
  14.  *  above shareware and copyright notices and this permission notice
  15.  *  appear in all copies and their documentation.
  16.  *
  17.  *  This software may be modified for your own use, but modified versions
  18.  *  may not be distributed without prior consent of the author.
  19.  *
  20.  *  This software is provided "as is" without expressed or implied
  21.  *  warranty of any kind.
  22.  *
  23.  *.
  24.  *
  25.  *  Purpose:
  26.  *    Place various simple geometric figures into image. The bitmaps is
  27.  *    in bm.h while the actual drawing routine in gl_util.c and ps.c.
  28.  *    It is sort of bad that all locations refers to the CENTER of the
  29.  *    sgfs and NOT the lower left  corner.
  30.  *
  31.  *    Code is a little more complicated than it should be because
  32.  *    doublebuffering in over/pup is generally not supported in hardware.
  33.  *    Need to simulate it. It appear working ok, but speed is not too good.
  34.  */
  35.  
  36. #if !defined(lint) && defined(F_ID)
  37. char *id_mk = "$Id: marking.c,v 0.91 1994/02/20 00:53:16 zhao Pre-Release $";
  38. #endif
  39.  
  40. #include "bit.h"
  41. #include "extern.h"
  42. #include "bm.h"            /* the bitmaps. */
  43.  
  44. /******************* Limits and defines **********************/
  45.  
  46.  
  47. /********************************************************
  48.  * If NO_OP_DBL is defined, double buffer simulation in
  49.  * over/pup plane will be suppressed.
  50.  ********************************************************/
  51.  
  52. /* #define NO_OP_DBL */
  53.  
  54. #define MAXOBJS   25        /* max no. of different objects */
  55. #define MAXOSIZE  600        /* max size of the objects      */
  56. #define MAXSAVE   101        /* max no. of objs per image    */
  57.  
  58. /*************** Local varialbes, excluding GUI *************/
  59.  
  60. static float mapx = 1.0, mapy = 1.0;
  61. static int pixels = 1;        /* units of measurement           */
  62. static int orix, oriy;        /* origin of measurement          */
  63. static int x, y;        /* position relative to window    */
  64. static int w = 20, h = 20;    /* current size in pixels         */
  65. static int angle, langle;    /* angle of rotation, deci-degree */
  66. static int lx, ly, lw, lh;    /* last position and size         */
  67. static int lwidth = 1;        /* line width                     */
  68. static int llwidth = 1;        /* line width                     */
  69. static int bcolor = 1;        /* over/pup index used            */
  70. static int xy = 1;        /* if keep aspect ratio           */
  71. static int reportr;        /* distance reporting             */
  72. static int immediate = 1;    /* rendering method               */
  73.  
  74. /* Default color */
  75. static int dcol[] =
  76. {
  77.     0xff, 0xff, 0, 0
  78. };
  79.  
  80. /*********** local functions and structures *******************/
  81.  
  82. typedef void (*GL_draw) (int, int, int, int, int, int);
  83. typedef const char *PS_draw;
  84.  
  85. static void mark_move(void);
  86. static void mark_moving(long);
  87. static void mark_events(IPTR, long, short);
  88. static int mark_wm_event(IPTR, int);
  89. static void mark_draw(int, int);
  90. static void mark_doit(IPTR, int, int, int, int);
  91.  
  92. /* Structure for simple geometric figures */
  93. typedef struct
  94.   {
  95.       const char *name;        /* name. Must not be null  */
  96.       char *bits;        /* bitmaps for the sgf     */
  97.       GL_draw how;        /* GL drawing routine      */
  98.       const char *psdraw;    /* PS drawing commands     */
  99.       int fill;            /* If filled sgf           */
  100.   }
  101. Obj_t;
  102.  
  103. /**************************************************************/
  104. /* all PostScript drawings are defined in ps.c.  */
  105. extern const char ps_plus[];
  106. extern const char ps_circ[], ps_rect[];
  107. extern const char ps_tri[], ps_star[];
  108. extern const char ps_arrow[], ps_hdist[], ps_line[];
  109.  
  110. /****** All objects definations ********************************/
  111.  
  112. static const Obj_t objs[] =
  113. {
  114.     {"Plus", plus_bits, gl_plus, ps_plus, 0},    /* plus */
  115.     {"Hdist", hdist_bits, gl_hdist, ps_hdist, 0},    /* |---| */
  116.     {"Delta", tri_bits, gl_tri, ps_tri, 0},    /* triangle */
  117.     {"DeltaF", ftri_bits, gl_tri, ps_tri, 1},    /* filled  */
  118.     {"Circ", circ_bits, gl_circ, ps_circ, 0},    /* circle */
  119.     {"CircF", fcirc_bits, gl_circ, ps_circ, 1},    /* filled */
  120.     {"Rect", rect_bits, gl_rect, ps_rect, 0},    /* rectangle */
  121.     {"RectF", frect_bits, gl_rect, ps_rect, 1},    /* filled   */
  122.     {"Star", star_bits, gl_star, ps_star, 0},
  123.     {"StarF", fstar_bits, gl_star, ps_star, 1},
  124.     {"Arrow", arrow_bits, gl_arrow, ps_arrow, 1},
  125.     {"Line", line_bits, gl_line, ps_line, 0}
  126. };
  127.  
  128. static int totalobjs = sizeof(objs) / sizeof(objs[0]);
  129. static int currentobj, cfill;
  130. static GL_draw cdraw;        /* curerent drawing routine */
  131.  
  132. /*********** GUI stuff ***************************************/
  133. static FL_FORM *tobj;
  134.  
  135. /* create the forms containing bitmaps for the symbols */
  136. static void create_form_tobj(void);
  137. static void handle_bmcb(FL_OBJECT * ob, long p);
  138. static void save_it(int, int, int, int, int, int, rgba_t, ci_t);
  139. static void show_map_unit(float, float);
  140. static void report_distance(int, int);
  141. static void report_size(int, int);
  142. static void report_rotation(float);
  143. static void save_bcolor(void);
  144. static void restore_bcolor(void);
  145. static void origin_cb(FL_OBJECT *, long);
  146. static void map_slider(void);
  147.  
  148. /********************************************************************
  149.  * non-interactively set origin. Always relative to ll corner of img
  150.  **********************************************************************/
  151. static int niorix, nioriy;
  152.  
  153. void
  154. set_marking_origin(int ox, int oy)
  155. {
  156.     niorix = ox;
  157.     nioriy = oy;
  158. }
  159.  
  160.  
  161. /***********************************************************************
  162.  * mark specific position within the image with simple geometric figures
  163.  * Global entry point
  164.  ************************************************************************/
  165. int
  166. img_marking(IPTR im)
  167. {
  168.     short val;
  169.     long dev;
  170.  
  171.     cdraw = objs[currentobj].how;
  172.     cfill = objs[currentobj].fill;
  173.  
  174.     if (bcolor >= over_pup_colors)
  175.     bcolor = over_pup_colors - 1;
  176.  
  177.     if (bcolor == 0)        /* avoid interference with WM */
  178.     bcolor = 1;
  179.     save_bcolor();
  180.  
  181.     set_use_calloc(1);
  182.  
  183.     /* how to handle window resize, repositioning */
  184.     install_wm_handler(mark_wm_event);
  185.  
  186.     /* initialize position */
  187.     mark_wm_event(im, 0);
  188.  
  189.     create_form_tobj();
  190.     show_map_unit(mapx, mapy);
  191.  
  192.     /* do this to get origin right */
  193.     x = niorix + im->xi;
  194.     y = nioriy + im->yi;
  195.     origin_cb(0, 0);
  196.  
  197.     bit_show_form(tobj, FL_PLACE_MOUSE, 0, "Objects");
  198.  
  199.     handle_bmcb(0, currentobj);
  200.     mark_draw(currentobj, bcolor);
  201.  
  202.     report_distance(x, y);
  203.  
  204.     while ((dev = bit_qread(&val)) != KEYBD || val != 27)
  205.     mark_events(im, dev, val);
  206.  
  207.     /* done. Clean up */
  208.  
  209.     clear_over_pup();
  210.     remove_wm_handler(mark_wm_event);
  211.     bit_hide_form(tobj);
  212.     set_current_window(win_id);
  213.     drawmode(NORMALDRAW);
  214.     linewidth(1);        /* line width is shared among all buffers */
  215.     restore_bcolor();
  216.     hide_rect_size();
  217.     hide_mouse_position();
  218.     set_use_calloc(0);
  219.     hide_getcolor();
  220.     return 0;
  221. }
  222.  
  223. /*********************************************************
  224.  * Save current position
  225.  *********************************************************/
  226. static void
  227. save_position(void)
  228. {
  229.     lx = x;
  230.     ly = y;
  231.     lw = w;
  232.     lh = h;
  233.     llwidth = lwidth;
  234.     langle = angle;
  235. }
  236.  
  237.  
  238. /**********************************************************
  239.  * given a name, find index
  240.  ************************************************************/
  241. static int
  242. sgf_get_index(const char *p)
  243. {
  244.     int i, k;
  245.  
  246.     if (!p || !*p)
  247.     return 0;
  248.  
  249.     for (i = k = 0; !k && i < totalobjs; i++)
  250.     k = strcmp(objs[i].name, p) == 0;
  251.  
  252.     return k ? --i : 0;
  253. }
  254.  
  255.  
  256. /**********************************************************
  257.  * Global routine that set the units  of measure
  258.  ***********************************************************/
  259. void
  260. set_marking_units(float mx, float my)
  261. {
  262.     if (mx > 0.0)
  263.     mapx = mx;
  264.     if (my > 0.0)
  265.     mapy = my;
  266. }
  267.  
  268. /******************************************************************
  269.  * Clear up the old one and draw a new one. No set_current_windows, no
  270.  * buffer switch etc.
  271.  *****************************************************************/
  272. static void
  273. mark_draw_only(int ind, int bc)
  274. {
  275.     static int lastind;
  276.     int noclear;
  277.  
  278.  
  279.     /* if same object but larger, there is no need to clear screen. */
  280.     noclear = (ind == lastind) &&
  281.     (langle == angle) &&
  282.     (lwidth >= llwidth) &&
  283.     (lx == x) && (ly == y) && (lw <= w) && (lh <= h) && cfill;
  284.  
  285.     /* arrow is a special case: it has cfill but not really filled */
  286.     if (!noclear || cdraw == gl_arrow)
  287.       {
  288.       color(0);
  289.       cdraw(lx, ly, lw, lh, cfill, langle);
  290.       currentobj = ind;
  291.       cfill = objs[ind].fill;
  292.       cdraw = objs[ind].how;
  293.       }
  294.     lastind = ind;
  295.  
  296.     /* draw the new one */
  297.     color(bc);
  298.     cdraw(x, y, w, h, cfill, angle);
  299.     save_position();
  300. }
  301.  
  302. #ifndef NO_OP_DBL
  303. static void mark_rasterize(void);
  304. #else
  305. #define mark_rasterize()
  306. #endif
  307.  
  308. /**********************************************************************
  309.  * Draw the current object in the over/pup plane and taking care of
  310.  * window and framebuffer as well
  311.  *********************************************************************/
  312. static void
  313. mark_draw(int ind, int bc)
  314. {
  315.     long owin = winget();
  316.  
  317.     set_current_window(win_id);
  318.     reshapeviewport();
  319.     switch_frame_buffer();
  320.     linewidth(lwidth);
  321.  
  322.     mark_draw_only(ind, bc);
  323.  
  324.     mark_rasterize();
  325.  
  326.     set_current_window(win_id);
  327.     reshapeviewport();
  328.     drawmode(NORMALDRAW);
  329.     set_current_window(owin);
  330. }
  331.  
  332. /*******************************************************************
  333.  * Do a complete draw after refreshing over/pup plane
  334.  *******************************************************************/
  335. static void
  336. complete_draw(int ind, int bc)
  337. {
  338.     clear_over_pup();
  339.     set_current_window(win_id);
  340.     switch_frame_buffer();
  341.     linewidth(lwidth);
  342.  
  343.     currentobj = ind;
  344.     cfill = objs[ind].fill;
  345.     cdraw = objs[ind].how;
  346.  
  347.     color(bc);
  348.     cdraw(x, y, w, h, cfill, angle);
  349.     mark_rasterize();
  350.  
  351.     save_position();
  352.     set_current_window(win_id);
  353.     drawmode(NORMALDRAW);
  354. }
  355.  
  356. /************************************************************
  357.  * handle window re-size and reposition events
  358.  *************************************************************/
  359. static int
  360. mark_wm_event(IPTR im, int wm)
  361. {
  362.     static int imxi, imyi;
  363.  
  364.     if (!wm)
  365.       {
  366.       x = lx = (im->xi > 0) ? im->xi : 1;
  367.       y = ly = (im->yi > 0) ? im->yi : 1;
  368.       if (IS_CI(im))
  369.         {
  370.         dcol[3] = im->cmap->colors - 2;
  371.         dcol[0] = im->cmap->ct[0][dcol[3]];
  372.         dcol[1] = im->cmap->ct[1][dcol[3]];
  373.         dcol[2] = im->cmap->ct[2][dcol[3]];
  374.         }
  375.       }
  376.     else
  377.       {
  378.       /* x and y must be unchanged relative to image */
  379.       x += (im->xi - imxi);
  380.       y += (im->yi - imyi);
  381.       complete_draw(currentobj, bcolor);
  382.       }
  383.     imxi = im->xi;
  384.     imyi = im->yi;
  385.     return 0;
  386. }
  387.  
  388. /*****************************************************************
  389.  * How to handle keyboad events
  390.  ****************************************************************/
  391. static long
  392. mark_keybd(int val)
  393. {
  394.     int ret = 0;
  395.     static int step = 1;
  396.     int re_ras = 0;        /* if re-rasterize the object */
  397.  
  398.     switch (val)
  399.       {
  400.       case 'r':
  401.       angle -= step * 10;
  402.       if (angle < -3600)
  403.           angle += 3600;
  404.       re_ras = 1;
  405.       break;
  406.       case 'R':
  407.       angle += step * 10;
  408.       if (angle > 3600)
  409.           angle -= 3600;
  410.       re_ras = 1;
  411.       break;
  412.       case 'x':
  413.       if ((w -= step) < 1)
  414.           w = 1;
  415.       re_ras = 1;
  416.       break;
  417.       case 'X':
  418.       if ((w += step) > MAXOSIZE)
  419.           w = MAXOSIZE;
  420.       re_ras = 1;
  421.       break;
  422.       case 'y':
  423.       if ((h -= step) < 1)
  424.           h = 1;
  425.       re_ras = 1;
  426.       break;
  427.       case 'Y':
  428.       if ((h += step) > MAXOSIZE)
  429.           h = MAXOSIZE;
  430.       re_ras = 1;
  431.       break;
  432.       case 'h':
  433.       case 'H':
  434.       x -= step;
  435.       break;
  436.       case 'L':
  437.       case 'l':
  438.       x += step;
  439.       break;
  440.       case 'j':
  441.       case 'J':
  442.       y -= step;
  443.       break;
  444.       case 'K':
  445.       case 'k':
  446.       y += step;
  447.       break;
  448.       default:
  449.       if (val > '0' && val <= '9')
  450.           step = val - '0';
  451.       else
  452.           ret = val;
  453.       break;
  454.       }
  455.  
  456.     if (re_ras)
  457.       {
  458.       mark_draw(currentobj, bcolor);
  459.       report_rotation(0.1 * angle);
  460.       report_size(w, h);
  461.       }
  462.     else
  463.     mark_move();
  464.     return ret;
  465. }
  466.  
  467. /***********************************************************************
  468.  * All  GL  events
  469.  *********************************************************************/
  470. /* ARGSUSED */
  471. static void
  472. mark_events(IPTR im, long dev, short val)
  473. {
  474.     switch (dev)
  475.       {
  476.       case KEYBD:
  477.       mark_keybd(val);
  478.       break;
  479.       case UPARROWKEY:
  480.       if (val)
  481.           mark_keybd('k');
  482.       break;
  483.       case DOWNARROWKEY:
  484.       if (val)
  485.           mark_keybd('j');
  486.       break;
  487.       case LEFTARROWKEY:
  488.       if (val)
  489.           mark_keybd('h');
  490.       break;
  491.       case RIGHTARROWKEY:
  492.       if (val)
  493.           mark_keybd('l');
  494.       break;
  495.       case LEFTMOUSE:
  496.       case MIDDLEMOUSE:
  497.       if (val)
  498.           mark_moving(dev);
  499.       break;
  500.       default:
  501.       break;
  502.       }
  503. }
  504.  
  505. #ifdef NO_OP_DBL
  506. #define dbl_mark_move sgl_mark_move
  507. #define dbl_mark_moving sgl_mark_moving
  508. #else
  509. /*****************************************************************
  510.  * Get current object in rasterized form.
  511.  * feedback should be the way to get the rasterized object, but it
  512.  * is not portable, too lazy to do it. Cheat here
  513.  ******************************************************************/
  514. static ci_t **cfig;
  515. static int objbw, objbh;
  516.  
  517. static void
  518. mark_rasterize(void)
  519. {
  520.     int bx, by, bw, bh;
  521.     register ci_t *s;
  522.     static int lastrasw, lastrash, lastlwidth;
  523.     static int lastrotate;
  524.     static GL_draw lastdraw;
  525.     static int incomplete;
  526.     int halflw = (lwidth + 1) / 2;
  527.     int sameobj, openobj;
  528.  
  529.     if (!simu_op_dblbuf)
  530.     return;
  531.  
  532.     /* check if same object */
  533.     sameobj = (lastlwidth == lwidth) &&
  534.     (lastrotate == angle) &&
  535.     (lastrasw == w && lastrash == h) &&
  536.     (lastdraw == cdraw);
  537.  
  538.     openobj = (cfill == 0 || cdraw == gl_arrow);
  539.  
  540.     if ((openobj || sameobj) && !incomplete)
  541.     return;
  542.  
  543.     find_bbox(x - halflw, y - halflw, w + (lwidth + 1), h + (lwidth + 1),
  544.           0.1 * angle, &bx, &by, &bw, &bh);
  545.  
  546.     bh += lwidth + 1;
  547.     bw += lwidth + 1;
  548.  
  549.     /* it is important to center (x,y) */
  550.     bx = x - (bw / 2);
  551.     by = y - (bh / 2);
  552.  
  553.     /* get buffer for the rasterized object */
  554.     if (cfig)
  555.     free_mat(cfig);
  556.     cfig = get_mat(bh, bw, sizeof(**cfig));
  557.  
  558.     rectread(bx, by, bx + bw - 1, by + bh - 1, cfig[0]);
  559.  
  560.     incomplete = (bx <= 0 || (bx + bw - 1) >= win_w ||
  561.           (by <= 0 || (by + bh - 1) >= win_h));
  562.  
  563.     /* mask off the garbarge */
  564.     s = cfig[0] + bw * bh;
  565.     while (--s >= cfig[0])
  566.     *s = ((*s & bcolor) != bcolor) ? 0 : bcolor;
  567.  
  568.     objbw = bw;
  569.     objbh = bh;
  570.     lastrasw = w;
  571.     lastrash = h;
  572.     lastdraw = cdraw;
  573.     lastrotate = angle;
  574.     lastlwidth = lwidth;
  575.  
  576. #ifdef MDEBUG
  577.     M_debug("MarkRasterize", "Done");
  578. #endif
  579.  
  580. }
  581.  
  582. /****************************************************************
  583.  * Move mark without flickering, i.e., simulating double buffering.
  584.  * Doesn't take care window, buffer etc.
  585.  * (x,y) new location
  586.  ****************************************************************/
  587. static void
  588. dbl_mark_move(void)
  589. {
  590.     int x1, x2, y1, y2;
  591.     static ci_t **scrn;
  592.     int sw, sh;
  593.     int halfw = objbw / 2 + 1, halfh = objbh / 2 + 1;
  594.  
  595.     x1 = Min(lx, x) - 1;
  596.     x2 = Max(lx, x) + 1;
  597.  
  598.     y1 = Min(ly, y) - 1;
  599.     y2 = Max(ly, y) + 1;
  600.  
  601.     sw = x2 - x1 + 1 + objbw + 2;
  602.     sh = y2 - y1 + 1 + objbh + 2;
  603.  
  604.     (report_mouse ? show_mouse_position : report_distance) (x, y);
  605.  
  606.     if (scrn)
  607.     free_mat(scrn);
  608.  
  609.     scrn = get_mat(sh, sw, sizeof(ci_t));
  610.  
  611.     put_submat(scrn, sh, sw, cfig, (y - y1) + 1, (x - x1) + 1,
  612.            objbh, objbw, sizeof(ci_t));
  613.  
  614.     x1 -= halfw;
  615.     y1 -= halfh;
  616.  
  617.     rectwrite(x1, y1, x1 + sw - 1, y1 + sh - 1, scrn[0]);
  618.     save_position();
  619. }
  620.  
  621. /********************************************************************
  622.  * Simulate a double buffer in over/pup plane
  623.  *******************************************************************/
  624. static void
  625. dbl_mark_moving(long dev)
  626. {
  627.     do
  628.       {
  629.       get_mouse(&x, &y);
  630.       x -= win_xo;
  631.       y -= win_yo;
  632.       if (lx - x || ly - y)
  633.           dbl_mark_move();
  634.       }
  635.     while (getbutton(dev));
  636.  
  637. #ifdef MDEBUG
  638.     M_debug("MoveMark", "Simulated doublebuffer");
  639. #endif
  640.  
  641. }
  642.  
  643. #endif /* NO_OP_DBL */
  644.  
  645. /***********************************************************
  646.  * Continuously move mark as long as mouse is down
  647.  ***********************************************************/
  648.  
  649. static void
  650. sgl_mark_move(void)
  651. {
  652.     /* draw it will set lx, ly */
  653.     mark_draw_only(currentobj, bcolor);
  654.     (report_mouse ? show_mouse_position : report_distance) (x, y);
  655. }
  656.  
  657. static void
  658. sgl_mark_moving(long dev)
  659. {
  660.     do
  661.       {
  662.       get_mouse(&x, &y);
  663.       x -= win_xo;
  664.       y -= win_yo;
  665.       if (x - lx || y - ly)
  666.         {
  667.         (report_mouse ? show_mouse_position : report_distance) (x, y);
  668.         mark_draw(currentobj, bcolor);
  669.         }
  670.       }
  671.     while (getbutton(dev));
  672.  
  673. #ifdef MDEBUG
  674.     M_debug("MoveMark", "single");
  675. #endif
  676.  
  677. }
  678.  
  679.  
  680. /*************************************************************
  681.  * Dragging the current object
  682.  *************************************************************/
  683.  
  684. static void
  685. mark_moving(long dev)
  686. {
  687.     /* another chance to re-rasterize */
  688.     get_mouse(&x, &y);
  689.     x -= win_xo;
  690.     y -= win_yo;
  691.     mark_draw(currentobj, bcolor);
  692.  
  693.     set_current_window(win_id);
  694.     switch_frame_buffer();
  695.     ((cfill && cdraw != gl_arrow && simu_op_dblbuf && cfig) ?
  696.      dbl_mark_moving : sgl_mark_moving) (dev);
  697.     set_current_window(win_id);
  698.     drawmode(NORMALDRAW);
  699. }
  700.  
  701. /******************************************************************
  702.  * move current object to a new location
  703.  ******************************************************************/
  704.  
  705. static void
  706. mark_move(void)
  707. {
  708.     set_current_window(win_id);
  709.     switch_frame_buffer();
  710.     ((cfill && simu_op_dblbuf) ? dbl_mark_move : sgl_mark_move) ();
  711.     drawmode(NORMALDRAW);
  712. }
  713.  
  714. static FL_OBJECT *bms[MAXOBJS], *hb[MAXOBJS], *sl[2];
  715. static FL_OBJECT *otext, *rtext, *dtext;
  716. static int totalshown, offset;
  717. static FL_OBJECT *ix, *iy, *mxi, *myi, *ingrp;
  718. #define FL_BMCOLOR   520
  719.  
  720. static void
  721. show_map_unit(float mx, float my)
  722. {
  723.     fl_set_input(mxi, ftoa(mx, 5));
  724.     fl_set_input(myi, ftoa(my, 5));
  725. }
  726.  
  727. /*********************************************************************
  728.  * report distance from the origin: Here xx & yy are the mouse position
  729.  * relative to window.
  730.  *********************************************************************/
  731.  
  732. #include <math.h>
  733. static void
  734. report_distance(int xx, int yy)
  735. {
  736.     float dx, dy;
  737.  
  738.     fl_freeze_form(tobj);
  739.     if (pixels)
  740.       {                /* absolute coordinates */
  741.       fl_set_input(ix, itoa((xx - orix)));
  742.       fl_set_input(iy, itoa((yy - oriy)));
  743.       dx = (xx - orix);
  744.       dy = (yy - oriy);
  745.       }
  746.     else
  747.       {                /* user coord */
  748.       dx = mapx * (xx - orix);
  749.       dy = mapy * (yy - oriy);
  750.       fl_set_input(ix, ftoa(dx, 5));
  751.       fl_set_input(iy, ftoa(dy, 5));
  752.       }
  753.     fl_unfreeze_form(tobj);
  754.  
  755.     if (reportr)
  756.     fl_set_object_label(dtext, ftoa(sqrt(dx * dx + dy * dy), 2));
  757. }
  758.  
  759. /*************************************************************
  760.  * Show object in current selected units
  761.  ************************************************************/
  762.  
  763. static void
  764. report_size(int width, int height)
  765. {
  766.  
  767.     fl_freeze_form(tobj);
  768.     if (pixels)
  769.       {
  770.       fl_set_slider_value(sl[0], width);
  771.       fl_set_slider_value(sl[1], height);
  772.       }
  773.     else
  774.       {
  775.       fl_set_slider_value(sl[0], mapx * width);
  776.       fl_set_slider_value(sl[1], mapy * height);
  777.       }
  778.     fl_unfreeze_form(tobj);
  779. }
  780.  
  781.  
  782. /*********************************************************************
  783.  * draw the object in normal buffer, relative to image, in units of pixels
  784.  *
  785.  **********************************************************************/
  786. static void
  787. mark_doit(IPTR im, int xx, int yy, int ww, int hh)
  788. {
  789.     long owin = winget();
  790.     rgba_t cc = Pack(dcol[0], dcol[1], dcol[2]);
  791.     int bx, by, bw, bh, halflw;
  792.  
  793.  
  794.     set_current_window(win_id);
  795.     drawmode(NORMALDRAW);
  796.     reshapeviewport();
  797.  
  798.     linewidth(lwidth);
  799.  
  800.     smooth_line_on(im, dcol, lwidth);
  801.  
  802.     cdraw(xx, yy, ww, hh, cfill, angle);
  803.  
  804. #ifndef SGL_BUF
  805.     if (doublebuffer)
  806.       {
  807.       swapbuffers();
  808.       cdraw(xx, yy, ww, hh, cfill, angle);
  809.       }
  810. #endif
  811.  
  812.     if (immediate)
  813.       {
  814.       /* if immediate, read the framebuffer */
  815.       halflw = (lwidth) / 2;
  816.       find_bbox(xx - halflw, yy - halflw, ww + lwidth, hh + lwidth,
  817.             0.1 * angle, &bx, &by, &bw, &bh);
  818.       bx -= halflw;
  819.       by -= halflw;
  820.       bw += lwidth;
  821.       bh += lwidth;
  822.       fb_to_ras(im, make_rect(bx, by, bw, bh));
  823.       }
  824.     else
  825.       {
  826.       /* save current figure */
  827.       save_it(currentobj, xx - im->xi, yy - im->yi, ww, hh,
  828.           lwidth, cc, dcol[3]);
  829.       }
  830.  
  831.     smooth_line_off(im, dcol);
  832.     clear_over_pup();
  833.  
  834.     set_current_window(owin);
  835. }
  836.  
  837. /* A dummy function to get call back prototype right */
  838. /* ARGSUSED */
  839. static void
  840. doit(FL_OBJECT * ob, long p)
  841. {
  842.     int xx = x, yy = y;
  843.     mark_doit(imgptr, xx, yy, w, h);
  844. }
  845.  
  846. /******************************************************
  847.  * User input for units
  848.  ******************************************************/
  849.  
  850. #include <stdlib.h>
  851. static void
  852. map_cb(FL_OBJECT * ob, long p)
  853. {
  854.     const char *q = fl_get_input(ob);
  855.     float tmp;
  856.  
  857.     if (p == 1)
  858.       {
  859.       if ((tmp = atof(q)) <= 0.0)
  860.         {
  861.         fl_set_input(ob, ftoa(mapx, 5));
  862.         tmp = mapx;
  863.         }
  864.       mapx = tmp;
  865.       }
  866.     else
  867.       {
  868.       if ((tmp = atof(q)) <= 0.0)
  869.         {
  870.         fl_set_input(ob, ftoa(mapy, 5));
  871.         tmp = mapy;
  872.         }
  873.       mapy = tmp;
  874.       }
  875.     if (!pixels)
  876.     map_slider();
  877.     report_distance(x, y);
  878. }
  879.  
  880. /***************************************************************
  881.  * With the given units and MAXOBJSIZE, set the slider
  882.  ***************************************************************/
  883. #include <math.h>
  884. static void
  885. map_slider(void)
  886. {
  887.     int xp, yp;
  888.  
  889.     fl_freeze_form(tobj);
  890.     if (!pixels)
  891.       {                /* use user coordinates system */
  892.       xp = (mapx < 1.0) ? -(log10(mapx) - 0.95) : 0;
  893.       yp = (mapy < 1.0) ? -(log10(mapy) - 0.95) : 0;
  894.       fl_set_slider_precision(sl[0], xp);
  895.       fl_set_slider_precision(sl[1], yp);
  896.       fl_set_slider_step(sl[0], mapx);
  897.       fl_set_slider_step(sl[1], mapy);
  898.       fl_set_slider_bounds(sl[0], 0.0, (mapx * MAXOSIZE));
  899.       fl_set_slider_bounds(sl[1], 0.0, (mapy * MAXOSIZE));
  900.       fl_set_slider_value(sl[0], (mapx * w));
  901.       fl_set_slider_value(sl[1], (mapy * h));
  902.       }
  903.     else
  904.       {
  905.       fl_set_slider_precision(sl[0], 0);
  906.       fl_set_slider_precision(sl[1], 0);
  907.       fl_set_slider_step(sl[0], 1);
  908.       fl_set_slider_step(sl[1], 1);
  909.       fl_set_slider_bounds(sl[0], 0.0, MAXOSIZE);
  910.       fl_set_slider_bounds(sl[1], 0.0, MAXOSIZE);
  911.       fl_set_slider_value(sl[0], w);
  912.       fl_set_slider_value(sl[1], h);
  913.       }
  914.     fl_unfreeze_form(tobj);
  915. }
  916.  
  917. /***************************************************************
  918.  * A new location is input from keyboard
  919.  **************************************************************/
  920. static void
  921. position_cb(FL_OBJECT * ob, long p)
  922. {
  923.     const char *q = fl_get_input(ob);
  924.     float xx, yy;
  925.  
  926.     if (p == 0)
  927.       {
  928.       xx = atof(q);
  929.       x = pixels ? (xx + 0.5) : (xx / mapx + 0.5);
  930.       x += orix;
  931.       }
  932.     else
  933.       {
  934.       yy = atof(q);
  935.       y = pixels ? (yy + 0.5) : (yy / mapy + 0.5);
  936.       y += oriy;
  937.       }
  938.     mark_draw(currentobj, bcolor);
  939. }
  940.  
  941.  
  942. /*********************************************************************
  943.  * Since bcolor is an index in over/pup plane and we will map it
  944.  * to different colors, better save it
  945.  *******************************************************************/
  946. static short bc[3];
  947.  
  948. static void
  949. save_bcolor(void)
  950. {
  951.     switch_frame_buffer();
  952.     getmcolor(bcolor, bc, bc + 1, bc + 2);
  953.  
  954.     /* default drawing color */
  955.     mapcolor(bcolor, dcol[0], dcol[1], dcol[2]);
  956.     drawmode(NORMALDRAW);
  957. }
  958.  
  959. static void
  960. restore_bcolor(void)
  961. {
  962.     switch_frame_buffer();
  963.     mapcolor(bcolor, bc[0], bc[1], bc[2]);
  964.     drawmode(NORMALDRAW);
  965. }
  966.  
  967.  
  968.  
  969. /* ARGSUSED */
  970. static void
  971. handle_bmcb(FL_OBJECT * ob, long p)
  972. {
  973.     static int last = -1;
  974.  
  975.     if (last >= 0)
  976.       {
  977.       fl_set_object_color(bms[last], FL_BLACK, FL_MAGIC1);
  978.       fl_redraw_object(bms[last]);
  979.       }
  980.     last = p;
  981.     fl_set_object_color(bms[p], FL_BMCOLOR, FL_MAGIC2);
  982.     fl_redraw_object(bms[p]);
  983.     complete_draw(p + offset, bcolor);
  984. }
  985.  
  986. /******************************************************************/
  987.  
  988. /* routines related to saving and displaying by other routines */
  989. typedef struct
  990. {
  991.     int obj;            /* index into the  struct  */
  992.     int x, y, w, h, t;        /* dimensions              */
  993.     int angle;            /* in tenth of degrees     */
  994.     rgba_t color;        /* color of obj            */
  995.     ci_t ci;            /* color index             */
  996. }
  997. Save_obj;
  998.  
  999. static int totalsave;
  1000.  
  1001. /*
  1002.  * by defining saveobj to be pointers, we can save about 20 bytes each, or
  1003.  * MAXSAVE * 20, or 2K, not worth it
  1004.  */
  1005.  
  1006. static Save_obj saveobj[MAXSAVE];
  1007.  
  1008. /****************************************************************
  1009.  * Save current objects
  1010.  ****************************************************************/
  1011. static void
  1012. save_it(int ind, int cx, int cy, int cw, int ch, int t,
  1013.     rgba_t c, ci_t ci)
  1014. {
  1015.     Save_obj *p = saveobj + totalsave;
  1016.  
  1017.     p->obj = ind;
  1018.     p->x = cx;
  1019.     p->y = cy;
  1020.     p->w = cw;
  1021.     p->h = ch;
  1022.     p->color = c;
  1023.     p->ci = ci;
  1024.     p->t = t;
  1025.     p->angle = angle;
  1026.     if (++totalsave >= MAXSAVE)
  1027.     totalsave = MAXSAVE - 1;
  1028. }
  1029.  
  1030. /**************************************************************
  1031.  * Global routine to display all saved SGFs
  1032.  *************************************************************/
  1033. void
  1034. display_sgf(IPTR im)
  1035. {
  1036.     long owin;
  1037.     Save_obj *p = saveobj, *ps;
  1038.     const Obj_t *ob;
  1039.     int xi, yi;
  1040.     int olwidth = lwidth;
  1041.     int cc[4];
  1042.  
  1043.  
  1044.     if (!totalsave || !im || !im->ok)
  1045.     return;
  1046.  
  1047.     owin = winget();
  1048.     set_current_window(win_id);
  1049.     reshapeviewport();
  1050.     xi = im->xi;
  1051.     yi = im->yi;
  1052.  
  1053.     /*
  1054.      * it is sort of bad that we have to turn anti-aliasing on and off, but
  1055.      * have no choice lwidth != 1 does not work right
  1056.      */
  1057.  
  1058.     for (ps = p + totalsave; p < ps; p++)
  1059.       {
  1060.       set_current_window(win_id);
  1061.       linewidth(p->t);
  1062.       lwidth = p->t;
  1063.       cc[4] = p->ci;;
  1064.       Unpack(p->color, cc[0], cc[1], cc[2]);
  1065.       smooth_line_on(im, cc, lwidth);
  1066.       ob = objs + p->obj;
  1067.       ob->how(p->x + xi, p->y + yi, p->w, p->h, ob->fill, p->angle);
  1068.       smooth_line_off(im, cc);
  1069.       }
  1070.  
  1071.     /* must restore width to 1 */
  1072.     linewidth(1);
  1073.     set_current_window(owin);
  1074.     lwidth = olwidth;
  1075. }
  1076.  
  1077. /*********************************************************************
  1078.  * Write to and Read from disk the sgf
  1079.  *********************************************************************/
  1080.  
  1081. void
  1082. dump_sgf(FILE * fp)
  1083. {
  1084.     Save_obj *p = saveobj, *ps;
  1085.  
  1086.     fprintf(fp, "#SG %d\n", totalsave);
  1087.     fputs("Obj x y w h t r g b ci rot. Note (x,y) refers sgf's center\n", fp);
  1088.  
  1089.     for (ps = p + totalsave; p < ps; p++)
  1090.       {
  1091.       fprintf(fp, "#%s %d %d %d %d %d\n", objs[p->obj].name,
  1092.           p->x, p->y, p->w, p->h, p->t);
  1093.       fprintf(fp, "%g %g %g %d \n", C2NC(get_R(p->color)),
  1094.           C2NC(get_G(p->color)), C2NC(get_B(p->color)), (int) p->ci);
  1095.       fprintf(fp, "%d \n", p->angle);
  1096.       }
  1097. }
  1098.  
  1099. /**********************************************************************
  1100.  * Read in SGFs written by dump_sgf
  1101.  **********************************************************************/
  1102. void
  1103. load_sgf(IPTR im)
  1104. {
  1105.     int n, r, g, b, ci;
  1106.     Save_obj *p = saveobj + totalsave, *ps;
  1107.     char buf[100], nm[40];
  1108.     FILE *fp = im->fp;
  1109.     /* by using this, we can change Save_obj freely */
  1110.     int hx, hy, hw, hh, ht;
  1111.  
  1112.     while ((n = getc(fp)) != EOF && n != '#')
  1113.     ;
  1114.     if (n != '#' || (n = getc(fp)) != 'S' || (n = getc(fp)) != 'G')
  1115.     return;
  1116.  
  1117.     n = readint(fp);
  1118.     if (n <= 0)
  1119.     return;
  1120.  
  1121.     if (n >= MAXSAVE)
  1122.       {
  1123.       Bark("LoadSgf", "Too many of them. Keeping %d", MAXSAVE);
  1124.       n = MAXSAVE;
  1125.       return;
  1126.       }
  1127.     M_info("LoadSGF", "Total %d sgfs found", n);
  1128.  
  1129.     for (ps = p + n; p < ps; p++)
  1130.       {
  1131.       while (fgets(buf, sizeof(buf) - 1, fp) && buf[0] != '#')
  1132.           ;
  1133.       if (buf[0] != '#')    /* premature EOF */
  1134.           break;
  1135.       sscanf(buf + 1, "%s %d %d %d %d %d", nm, &hx, &hy, &hw, &hh, &ht);
  1136.       p->x = hx;
  1137.       p->y = hy;
  1138.       p->w = hw;
  1139.       p->h = hh;
  1140.       p->t = ht;
  1141.       r = (readfloat(fp) * PCMAXV + 0.4);
  1142.       g = (readfloat(fp) * PCMAXV + 0.4);
  1143.       b = (readfloat(fp) * PCMAXV + 0.4);
  1144.       p->color = Pack(r, g, b);
  1145.       ci = readpint(fp);
  1146.       p->ci = ci;
  1147.       if (ci < 0 || ci >= MAXCML)
  1148.           p->ci = 0;
  1149.       p->angle = readint(fp);
  1150.       p->obj = sgf_get_index(nm);
  1151.       }
  1152.     totalsave += n;
  1153. }
  1154.  
  1155. /********************************************************************
  1156.  * we only need to take care the RGB case because colormapped case
  1157.  * will be  taken care of automatically by system colormap
  1158.  ********************************************************************/
  1159. void
  1160. sgf_to_gray(void)
  1161. {
  1162.     register int q;
  1163.     register Save_obj *p = saveobj, *ps;
  1164.  
  1165.     for (ps = p + totalsave; p < ps; p++)
  1166.       {
  1167.       q = cpack2gray(p->color);
  1168.       p->color = Pack(q, q, q);
  1169.       }
  1170. }
  1171.  
  1172. /* take care of from RGB -> ci */
  1173. void
  1174. sgf_to_cmap(void)
  1175. {
  1176.     register Save_obj *p = saveobj, *ps;
  1177.  
  1178.     if (!IS_CI(imgptr))
  1179.     return;
  1180.     for (ps = p + totalsave; p < ps; p++)
  1181.     p->ci = cmap_closematch(imgptr->cmap,
  1182.              get_R(p->color), get_G(p->color), get_B(p->color));
  1183.  
  1184. }
  1185.  
  1186. void
  1187. del_marking(void)
  1188. {
  1189.     totalsave = 0;
  1190.     return;
  1191. }
  1192.  
  1193. /*********************************************************
  1194.  * Routines to get info for format capable of vectors
  1195.  *************************************************************/
  1196.  
  1197. int
  1198. number_of_sgf(void)
  1199. {
  1200.     return totalsave;
  1201. }
  1202.  
  1203. const char *
  1204. sgf_name(int n)
  1205. {
  1206.     return (saveobj[n].obj + objs)->name;
  1207. }
  1208.  
  1209. const char *
  1210. sgf_psdraw(int n)
  1211. {
  1212.     return (saveobj[n].obj + objs)->psdraw;
  1213. }
  1214.  
  1215. /******************************************************************
  1216.  * important info about an sgf: (x,y), (w,h), line width, closed path
  1217.  * and rotation angle
  1218.  *******************************************************************/
  1219. void
  1220. get_sgf_info(int n, int *xl, int *yl,
  1221.          int *wd, int *ht, int *t, int *fi, int *a)
  1222. {
  1223.  
  1224.     Save_obj *p = saveobj + n;
  1225.  
  1226.     if (n < 0 || n >= totalsave)
  1227.     return;
  1228.  
  1229.     *xl = p->x;
  1230.     *yl = p->y;
  1231.     *wd = p->w;
  1232.     *ht = p->h;
  1233.     *t = p->t;
  1234.     *a = (0.1 * p->angle);
  1235.     *fi = ((objs + saveobj[n].obj)->fill) != 0;
  1236. }
  1237.  
  1238. /*********************************************************************
  1239.  * in order to find the bounding box correctly, we need info about the
  1240.  * dimensions of all sgfs that sticks out of the image. Only return the abs
  1241.  * value of the portion that sticks out. Rotation is not considered which
  1242.  * could cause some error, but typically sgf's are small enuf to ignore it.
  1243.  *********************************************************************/
  1244.  
  1245. void
  1246. get_sgf_bounds(IPTR im, int *top, int *left, int *bottom, int *right)
  1247. {
  1248.     Save_obj *p = saveobj, *ps;
  1249.     int l = 0, b = 0, r = im->w, t = im->h;
  1250.     int w2, h2;
  1251.  
  1252.     for (ps = p + totalsave; p < ps; p++)
  1253.       {
  1254.       h2 = p->h / 2;
  1255.       w2 = p->w / 2;
  1256.       if (l > p->x - w2)
  1257.           l = p->x - w2;
  1258.       if (b > p->y - h2)
  1259.           b = p->y - h2;
  1260.       if (r < p->x + w2)
  1261.           r = p->x + w2;
  1262.       if (t < p->y + h2)
  1263.           t = p->y + h2;
  1264.       }
  1265.     /* return abs */
  1266.     *left = -l;
  1267.     *bottom = -b;
  1268.     *right = r - im->w;
  1269.     *top = t - im->h;
  1270. }
  1271.  
  1272. void
  1273. get_sgf_color(int n, int *r, int *g, int *b)
  1274. {
  1275.     int i;
  1276.  
  1277.     if (!imgptr)
  1278.     return;
  1279.     if (IS_CI(imgptr))
  1280.       {
  1281.       i = saveobj[n].ci;
  1282.       *r = imgptr->cmap->ct[0][i];
  1283.       *g = imgptr->cmap->ct[1][i];
  1284.       *b = imgptr->cmap->ct[2][i];
  1285.       }
  1286.     else
  1287.       {
  1288.       Unpack(saveobj[n].color, *r, *g, *b);
  1289.       }
  1290. }
  1291.  
  1292. /* ARGSUSED */
  1293. static void
  1294. del_dummy(FL_OBJECT * p, long q)
  1295. {
  1296.     del_marking();
  1297.     imgptr->io->display(imgptr, 0, 1);
  1298. }
  1299.  
  1300. /*******************************************************************
  1301.  * Flip thru all defined objects.
  1302.  * Should never been called if obj is less than that can be shown
  1303.  ********************************************************************/
  1304. /* ARGSUSED */
  1305. static void
  1306. more_cb(FL_OBJECT * ob, long p)
  1307. {
  1308.     int i;
  1309.  
  1310.     if (offset + totalshown < totalobjs)
  1311.     offset += totalshown;
  1312.     else if (offset >= totalshown)
  1313.     offset -= totalshown;
  1314.  
  1315.     fl_freeze_form(tobj);
  1316.     for (i = 0; i < totalshown && i + offset < totalobjs; i++)
  1317.       {
  1318.       fl_show_object(bms[i]);
  1319.       fl_activate_object(hb[i]);
  1320.       if (i + offset != currentobj)
  1321.           fl_set_object_color(bms[i], FL_BLACK, FL_MAGIC1);
  1322.       else
  1323.           fl_set_object_color(bms[i], FL_BMCOLOR, FL_MAGIC2);
  1324.       fl_set_bitmap(bms[i], BM_W, BM_H, objs[i + offset].bits);
  1325.       }
  1326.     for (; i < totalshown; i++)
  1327.       {
  1328.       fl_hide_object_only(bms[i]);
  1329.       fl_deactivate_object(hb[i]);
  1330.       }
  1331.     fl_unfreeze_form(tobj);
  1332. }
  1333.  
  1334. /*****************************************************
  1335.  * aspect ratio and coordinate system switch
  1336.  ******************************************************/
  1337. static void
  1338. misc_cb(FL_OBJECT * ob, long p)
  1339. {
  1340.     if (p == 2)
  1341.       {                /* aspect ration of obj */
  1342.       xy = fl_get_choice(ob) - 1;
  1343.       }
  1344.     else
  1345.       {
  1346.       pixels = fl_get_choice(ob) - 1;
  1347.       map_slider();
  1348.       report_distance(x, y);
  1349.       }
  1350. }
  1351.  
  1352. /* ARGSUSED */
  1353. static void
  1354. dist_cb(FL_OBJECT * ob, long p)
  1355. {
  1356.     reportr = fl_get_button(ob);
  1357. }
  1358.  
  1359. /****************************************************************
  1360.  * Set origin of measurement
  1361.  ***************************************************************/
  1362. /* ARGSUSED */
  1363. static void
  1364. origin_cb(FL_OBJECT * ob, long p)
  1365. {
  1366.     char ori[50];
  1367.  
  1368.     /* get the current position in pixels */
  1369.     orix = x;
  1370.     oriy = y;
  1371.     sprintf(ori, "%d,%d", orix, oriy);
  1372.     fl_set_object_label(otext, ori);
  1373.     report_distance(x, y);
  1374. }
  1375.  
  1376. /*******************************************************************
  1377.  * Select rendering method
  1378.  ******************************************************************/
  1379. /*ARGSUSED*/
  1380. static void
  1381. mode_cb(FL_OBJECT * ob, long q)
  1382. {
  1383.     immediate = fl_get_choice(ob) - 1;
  1384. }
  1385.  
  1386. /*************************************************************
  1387.  * What to do if different color is requested
  1388.  *************************************************************/
  1389. static void
  1390. handle_color_change(int c[])
  1391. {
  1392.     int i = currentobj - offset;
  1393.  
  1394.     switch_frame_buffer();
  1395.     /* need not change the drawing because it is always in colormap mode */
  1396.     mapcolor(bcolor, c[0], c[1], c[2]);
  1397.  
  1398.     /* take care of bitmaps */
  1399.     drawmode(NORMALDRAW);
  1400.  
  1401.     /* if visible: i is the index, offset the starting point */
  1402.     if (i >= 0 && i < totalshown)
  1403.       {
  1404.       fl_mapcolor(FL_BMCOLOR, c[0], c[1], c[2]);
  1405.       fl_redraw_object(bms[i]);
  1406.       }
  1407. }
  1408.  
  1409. /*************************************************************
  1410.  * Do this when color change is requested
  1411.  ************************************************************/
  1412. /*ARGSUSED */
  1413. static void
  1414. color_cb(FL_OBJECT * ob, long p)
  1415. {
  1416.  
  1417.     set_getcolor_cb(handle_color_change);
  1418.     /* non block */
  1419.     get_color(imgptr, dcol, 0);
  1420. }
  1421.  
  1422. /**************************************************************
  1423.  * Change line thickness: look bad if not line
  1424.  *************************************************************/
  1425. /*ARGSUSED*/
  1426. static void
  1427. thickness_cb(FL_OBJECT * ob, long p)
  1428. {
  1429.     int status;
  1430.  
  1431.     do
  1432.       {
  1433.       status = getint("Enter line thickness", &lwidth, 1, 50, 1);
  1434.       set_current_window(win_id);
  1435.       switch_frame_buffer();
  1436.       color(0);
  1437.       cdraw(x, y, w, h, cfill, angle);
  1438.       color(bcolor);
  1439.       linewidth(lwidth);
  1440.       cdraw(x, y, w, h, cfill, angle);
  1441.       }
  1442.     while (status == 0);
  1443.     mark_draw(currentobj, bcolor);
  1444. }
  1445.  
  1446. /****************************************************************
  1447.  * Change object size: if aspect ratio is to be kept, changing
  1448.  * x size should automatically set y size and vice versa
  1449.  ****************************************************************/
  1450. static void
  1451. size_cb(FL_OBJECT * ob, long p)
  1452. {
  1453.     float sx, sy;
  1454.  
  1455.     if (p == 0)            /* xsize */
  1456.       {
  1457.       sx = fl_get_slider_value(ob);
  1458.       if (xy)
  1459.           fl_set_slider_value(sl[1], sy = sx);
  1460.       else
  1461.           sy = fl_get_slider_value(sl[1]);
  1462.       }
  1463.     else
  1464.       {
  1465.       sy = fl_get_slider_value(ob);
  1466.       if (xy)
  1467.           fl_set_slider_value(sl[!p], sx = sy);
  1468.       else
  1469.           sx = fl_get_slider_value(sl[!p]);
  1470.       }
  1471.  
  1472.     /* if in user coordinates, convert to pixels */
  1473.     if (!pixels)
  1474.       {
  1475.       w = (sx / mapx + 0.5);
  1476.       h = (sy / mapy + 0.5);
  1477.       }
  1478.     else
  1479.       {
  1480.       w = (sx + 0.4);
  1481.       h = (sy + 0.4);
  1482.       }
  1483.  
  1484.     /* always show it in pixels */
  1485.     mark_draw(currentobj, bcolor);
  1486.     show_rect_size(w, h);
  1487. }
  1488.  
  1489. static void
  1490. report_rotation(float f)
  1491. {
  1492.     fl_set_object_label(rtext, ftoa(f, 1));
  1493. }
  1494.  
  1495. /*****************************************************
  1496.  * get rotation angle in deci-degrees
  1497.  *****************************************************/
  1498.  /* ARGSUSED */
  1499. static void
  1500. rotate_cb(FL_OBJECT * ob, long q)
  1501. {
  1502.  
  1503.     while (!get_orientation("Enter Rotation", &angle, 1))
  1504.       {
  1505.       if (langle - angle)
  1506.         {
  1507.         mark_draw(currentobj, bcolor);
  1508.         }
  1509.       }
  1510.     fl_set_object_label(rtext, ftoa(0.1 * angle, 1));
  1511.     mark_draw(currentobj, bcolor);
  1512. }
  1513.  
  1514. /*ARGSUSED*/
  1515. static void
  1516. mark_done(FL_OBJECT * ob, long q)
  1517. {
  1518.     fl_qenter(KEYBD, 27);
  1519. }
  1520. /********************************************************************
  1521.  * The form
  1522.  *******************************************************************/
  1523. static void
  1524. create_form_tobj(void)
  1525. {
  1526.  
  1527.     FL_OBJECT *obj;
  1528.     float xx, dx, yy, dy, x0;
  1529.     int i, j, k, ncol;
  1530.     static int ok;
  1531.  
  1532.     if (ok)
  1533.     return;            /* initialize static variables */
  1534.     fl_mapcolor(FL_BMCOLOR, dcol[0], dcol[1], dcol[2]);
  1535.  
  1536.     switch_frame_buffer();
  1537.     mapcolor(bcolor, dcol[0], dcol[1], dcol[2]);
  1538.     drawmode(NORMALDRAW);
  1539.  
  1540.     tobj = fl_bgn_form(FL_NO_BOX, 250.0, 310.0);
  1541.     obj = fl_add_box(FL_UP_BOX, 0.0, 0.0, 250.0, 310.0, "");
  1542.     obj = fl_add_button(FL_HB, 0.0, 0.0, 250.0, 310.0, "");
  1543.     fl_set_call_back(obj, help_cb, HELP_MARKING);
  1544.  
  1545.     obj = fl_add_box(FL_BORDER_BOX, 10.0, 40.0, 225.0, 110.0, "");
  1546.  
  1547.  
  1548.     /* the origin setting and misc control group */
  1549.     fl_bgn_group();
  1550.  
  1551.     x = 18.0;
  1552.     y = 208.0;
  1553.     dx = 70.0;
  1554.     dy = 23.0;
  1555.     obj = fl_add_box(FL_BORDER_BOX, 10.0, 155.0, 228.0, 80.0, "");
  1556.     obj = fl_add_button(FL_NB, x, y, dx, dy, "SetOrigin");
  1557.     fl_set_object_boxtype(obj, FL_ROUNDED_BOX);
  1558.     fl_set_object_lsize(obj, 10.0);
  1559.     fl_set_object_color(obj, FL_MAGIC1, FL_YELLOW);
  1560.     fl_set_call_back(obj, origin_cb, 0);
  1561.     obj = fl_add_button(FL_NB, x + dx, y, dx, dy, "Rotate");
  1562.     fl_set_object_boxtype(obj, FL_ROUNDED_BOX);
  1563.     fl_set_object_lsize(obj, 10.0);
  1564.     fl_set_object_color(obj, FL_MAGIC1, FL_YELLOW);
  1565.     fl_set_call_back(obj, rotate_cb, 0);
  1566.     obj = fl_add_button(FL_PB, x + 2 * dx, y, dx, dy, "DReport");
  1567.     fl_set_object_boxtype(obj, FL_ROUNDED_BOX);
  1568.     fl_set_object_color(obj, FL_MAGIC1, FL_YELLOW);
  1569.     fl_set_object_lsize(obj, 10.0);
  1570.     fl_set_call_back(obj, dist_cb, 0);
  1571.  
  1572.     y -= dy + 1;
  1573.     otext = obj = fl_add_text(FL_NT, x, y, dx, 20.0, "");
  1574.     fl_set_object_boxtype(obj, FL_ROUNDED_BOX);
  1575.     fl_set_object_lsize(obj, 10.0);
  1576.     fl_set_object_align(obj, FL_ALIGN_CENTER);
  1577.  
  1578.     rtext = obj = fl_add_text(FL_NT, x + dx, y, dx, 20.0, "0");
  1579.     fl_set_object_boxtype(obj, FL_ROUNDED_BOX);
  1580.     fl_set_object_lsize(obj, 10.0);
  1581.     fl_set_object_align(obj, FL_ALIGN_CENTER);
  1582.  
  1583.     dtext = obj = fl_add_text(FL_NT, x + 2.0 * dx, y, dx, 20.0, "0");
  1584.     fl_set_object_boxtype(obj, FL_ROUNDED_BOX);
  1585.     fl_set_object_lsize(obj, 10.0);
  1586.     fl_set_object_align(obj, FL_ALIGN_CENTER);
  1587.  
  1588.     y = 158.0;
  1589.     dx = 70;
  1590.     dy = 23;
  1591.     /* coordinate system to use */
  1592.     obj = fl_add_choice(FL_NC, x, y, dx, dy, "");
  1593.     fl_set_object_boxtype(obj, FL_ROUNDED_BOX);
  1594.     fl_set_choice_fontsize(obj, 10.0);
  1595.     fl_addto_choice(obj, "User");
  1596.     fl_addto_choice(obj, "Pixels");
  1597.     fl_set_choice(obj, pixels + 1);
  1598.     fl_set_call_back(obj, misc_cb, 0);
  1599.     x += dx;
  1600.  
  1601.     /* mode of operation */
  1602.     obj = fl_add_choice(FL_NC, x, y, dx, dy, "");
  1603.     fl_set_object_boxtype(obj, FL_ROUNDED_BOX);
  1604.     fl_set_choice_fontsize(obj, 10.0);
  1605.     fl_addto_choice(obj, "Deferred");
  1606.     fl_addto_choice(obj, "Immediate");
  1607.     fl_set_choice(obj, immediate + 1);
  1608.     fl_set_call_back(obj, mode_cb, 0);
  1609.  
  1610.     /* aspect ratio */
  1611.     x += dx;
  1612.     obj = fl_add_choice(FL_NC, x, y, dx, dy, "");
  1613.     fl_set_object_boxtype(obj, FL_ROUNDED_BOX);
  1614.     fl_set_choice_fontsize(obj, 10.0);
  1615.     fl_addto_choice(obj, "FreeASP");
  1616.     fl_addto_choice(obj, "KeepASP");
  1617.     fl_set_choice(obj, xy + 1);
  1618.     fl_set_call_back(obj, misc_cb, 2);
  1619.  
  1620.     fl_end_group();
  1621.  
  1622.     /* input group */
  1623.     ingrp = fl_bgn_group();
  1624.     ix = obj = fl_add_input(FL_FLOAT_INPUT, 35.0, 70.0, 60.0, 20.0, "X:");
  1625.     fl_set_object_boxtype(obj, FL_FRAME_BOX);
  1626.     fl_set_object_color(obj, 47, 51);
  1627.     fl_set_object_lsize(obj, 10.0);
  1628.     fl_set_call_back(obj, position_cb, 0);
  1629.     iy = obj = fl_add_input(FL_FLOAT_INPUT, 35.0, 50.0, 60.0, 20.0, "Y:");
  1630.     fl_set_object_boxtype(obj, FL_FRAME_BOX);
  1631.     fl_set_object_color(obj, 47, 51);
  1632.     fl_set_object_lsize(obj, 10.0);
  1633.     fl_set_call_back(obj, position_cb, 1);
  1634.     fl_end_group();
  1635.  
  1636.     fl_bgn_group();
  1637.     mxi = obj = fl_add_input(FL_FLOAT_INPUT, 135.0, 70.0, 70.0, 20.0, "Mx");
  1638.     fl_set_object_boxtype(obj, FL_FRAME_BOX);
  1639.     fl_set_object_color(obj, 47, 51);
  1640.     fl_set_object_lsize(obj, 10.0);
  1641.     fl_set_object_align(obj, FL_ALIGN_RIGHT);
  1642.     fl_set_input(obj, "1.0");
  1643.     fl_set_call_back(obj, map_cb, 0);
  1644.     myi = obj = fl_add_input(FL_FLOAT_INPUT, 135.0, 50.0, 70.0, 20.0, "My");
  1645.     fl_set_object_boxtype(obj, FL_FRAME_BOX);
  1646.     fl_set_object_color(obj, 47, 51);
  1647.     fl_set_object_lsize(obj, 10.0);
  1648.     fl_set_object_align(obj, FL_ALIGN_RIGHT);
  1649.     fl_set_input(obj, "1.0");
  1650.     fl_set_call_back(obj, map_cb, 1);
  1651.  
  1652.     obj = fl_add_button(FL_NORMAL_BUTTON, 95.0, 50.0, 40.0, 40.0, "OK");
  1653.     fl_set_object_boxtype(obj, FL_FRAME_BOX);
  1654.     fl_set_object_color(obj, 47, 9);
  1655.     fl_set_button_shortcut(obj, "po");
  1656.     fl_set_call_back(obj, doit, 0);
  1657.     fl_end_group();
  1658.  
  1659.     sl[0] = obj = fl_add_valslider(FL_HNS, 15.0, 120.0, 150.0, 20.0, "");
  1660.     fl_set_object_boxtype(obj, FL_BORDER_BOX);
  1661.     fl_set_object_color(obj, 47, 1);
  1662.     fl_set_object_lsize(obj, 10.0);
  1663.     fl_set_slider_bounds(obj, 1.0, MAXOSIZE);
  1664.     fl_set_slider_step(obj, 1.0);
  1665.     fl_set_slider_precision(obj, 0);
  1666.     fl_set_slider_value(obj, h);
  1667.     fl_set_call_back(obj, size_cb, 0);
  1668.     sl[1] = obj = fl_add_valslider(FL_HNS, 15.0, 100.0, 150.0, 20.0, "");
  1669.     fl_set_object_boxtype(obj, FL_BORDER_BOX);
  1670.     fl_set_object_color(obj, 47, 1);
  1671.     fl_set_object_lsize(obj, 10.0);
  1672.     fl_set_slider_bounds(obj, 1.0, MAXOSIZE);
  1673.     fl_set_slider_step(obj, 1.0);
  1674.     fl_set_slider_precision(obj, 0);
  1675.     fl_set_slider_value(obj, w);
  1676.     fl_set_call_back(obj, size_cb, 1);
  1677.  
  1678.     obj = fl_add_button(FL_NB, 170.0, 120.0, 60.0, 20.0, "Color");
  1679.     fl_set_object_boxtype(obj, FL_FRAME_BOX);
  1680.     fl_set_object_color(obj, 47, 4);
  1681.     fl_set_object_lsize(obj, 10.0);
  1682.     fl_set_call_back(obj, color_cb, 0);
  1683.     obj = fl_add_button(FL_NB, 170.0, 100.0, 60.0, 20.0, "Lwidth");
  1684.     fl_set_object_boxtype(obj, FL_FRAME_BOX);
  1685.     fl_set_object_color(obj, 47, 9);
  1686.     fl_set_object_lsize(obj, 10.0);
  1687.     fl_set_call_back(obj, thickness_cb, 0);
  1688.     /*
  1689.      * The bitmap groups max nine per row, could be seven, depending on
  1690.      * totalobjs
  1691.      */
  1692.     obj = fl_add_box(FL_BORDER_BOX, 8.0, 240.0, 230, 60.0, "");
  1693.     if (totalobjs < 18)        /* 9 per row */
  1694.     ncol = 9;
  1695.     else
  1696.       {
  1697.       ncol = 7;
  1698.       obj = fl_add_button(FL_NB, 230 - 40, 230, 45, 55, "More");
  1699.       fl_set_object_lsize(obj, 10.0);
  1700.       fl_set_call_back(obj, more_cb, 0);
  1701.       }
  1702.  
  1703.     dx = dy = 25;
  1704.     yy = 270.0;
  1705.     x0 = xx = 10;
  1706.     totalshown = ncol * 2;
  1707.     fl_bgn_group();
  1708.     for (i = k = 0; i < totalshown; i += ncol, xx = x0, yy -= dy)
  1709.       {
  1710.       for (j = 0; j < ncol; j++, xx += dx, k++)
  1711.         {
  1712.         if (k >= totalobjs)
  1713.             continue;
  1714.         bms[k] = obj = fl_add_bitmap(FL_NBM, xx, yy, dx, dy, "");
  1715.         fl_set_object_boxtype(obj, FL_FRAME_BOX);
  1716.         fl_set_bitmap(bms[k], BM_W, BM_H, objs[k].bits);
  1717.         hb[k] = obj = fl_add_button(FL_HB, xx, yy, dx, dy, "");
  1718.         fl_set_call_back(obj, handle_bmcb, k);
  1719.         }
  1720.       }
  1721.     totalshown = k;
  1722.     fl_end_group();
  1723.     obj = fl_add_button(FL_NB, 10.0, 10.0, 70.0, 25.0, "DelAll");
  1724.     fl_set_object_lsize(obj, 10.0);
  1725.     fl_set_call_back(obj, del_dummy, 0);
  1726.     obj = fl_add_button(FL_NB, 163.0, 10.0, 70.0, 25.0, "Done");
  1727.     fl_set_object_lsize(obj, 10.0);
  1728.     fl_set_call_back(obj, mark_done, 0);
  1729.     fl_end_form();
  1730.     fl_scale_form(tobj, 1.2, 1.1);
  1731.     ok = 1;
  1732. }
  1733.